package net.ufrog.common.spring.interceptor;

import net.ufrog.common.Logger;
import net.ufrog.common.app.App;
import net.ufrog.common.exception.ServiceException;
import net.ufrog.common.utils.Strings;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 令牌拦截器
 * 
 * @author ultrafrog
 * @version 1.0, 2014-07-03
 * @since 1.0
 */
public class TokenInterceptor implements HandlerInterceptor {

    private static final String DEFAULT_KEY	= "_token";

    /** 参数名称 */
    private String key = DEFAULT_KEY;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getParameter(key);
        if ((isTokenForced(handler) || !Strings.empty(token)) && !Strings.equals(token, App.current().getToken())) {
            Logger.warn("can not match between '%s' and '%s'", token, App.current().getToken());
            throw new ServiceException("the token is not match!", "exception.token");
        } else {
            App.current().updateToken();
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}

    /**
     * 读取参数名称
     *
     * @return 参数名称
     * @see #key
     */
    public String getKey() {
        return key;
    }

    /**
     * 设置参数名称
     *
     * @param key 参数名称
     * @see #key
     */
    public void setKey(String key) {
        this.key = key;
    }

    /**
     * 判断是否需要强制判断令牌
     *
     * @param handler 待判断对象
     * @return 判断结果
     */
    private Boolean isTokenForced(Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod method = (HandlerMethod) handler;
            TokenForced tokenForced = method.getMethod().getAnnotation(TokenForced.class);
            return (tokenForced != null);
        }
        return Boolean.FALSE;
    }
}
